package co.yixiang.modules.shop.rest;

import cn.hutool.core.util.StrUtil;
import co.yixiang.aop.log.Log;
import co.yixiang.domain.QiniuConfig;
import co.yixiang.exception.BadRequestException;
import co.yixiang.modules.shop.domain.YxInvestOrder;
import co.yixiang.modules.shop.domain.YxSystemConfig;
import co.yixiang.modules.shop.service.YxInvestOrderService;
import co.yixiang.modules.shop.service.YxStoreProductService;
import co.yixiang.modules.shop.service.YxSystemConfigService;
import co.yixiang.modules.shop.service.dto.YxInvestOrderDto;
import co.yixiang.modules.shop.service.dto.YxInvestOrderQueryCriteria;
import co.yixiang.modules.shop.service.dto.YxStoreProductDTO;
import co.yixiang.modules.shop.websocket.MsgType;
import co.yixiang.modules.shop.websocket.SocketMsg;
import co.yixiang.modules.shop.websocket.WebSocketServer;
import co.yixiang.service.KryConfigService;
import co.yixiang.service.QiNiuService;
import co.yixiang.service.dto.RefundApplyCriteia;
import co.yixiang.utils.SecurityUtils;
import co.yixiang.utils.TencentCOSUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author frq
 * @date 2020-06-10
 */
@Slf4j
@Api(tags = "认购订单管理")
@RestController
@RequestMapping("/api/yxInvestOrder")
public class YxInvestOrderController {
    @Autowired
    private YxInvestOrderService yxInvestOrderService;
    @Autowired
    private YxStoreProductService yxStoreProductService;
    @Autowired
    private YxSystemConfigService yxSystemConfigService;
    @Autowired
    private QiNiuService qiNiuService;

    @Autowired
    private KryConfigService kryConfigService;


    @GetMapping
    @Log("查询认购订单")
    @ApiOperation("查询认购订单")
    public ResponseEntity<Object> getYxInvestOrders(YxInvestOrderQueryCriteria criteria, Pageable pageable,
                                                    @RequestParam(name = "orderStatus") String orderStatus) {
        //订单状态查询
        if (StrUtil.isNotEmpty(orderStatus)) {
            switch (orderStatus) {
                case "0"://锁定
                    criteria.setInvestStatus(0);
                    break;
                case "1"://未支付
                    criteria.setPaid(0);
                    break;
                case "2"://审核中
                    criteria.setPaid(1);
                    criteria.setAuditStatus(0);
                    break;
                case "3"://审核不通过
                    criteria.setAuditStatus(2);
                    break;
                case "4"://认购中
                    criteria.setInvestStatus(3);
                    criteria.setAuditStatus(1);
                    break;
                case "5"://已到期
                    criteria.setInvestStatus(4);
                    break;
                case "6"://取消认购
                    criteria.setInvestStatus(9);
                    break;
                case "7"://支付超时
                    criteria.setInvestStatus(5);
                    break;

            }
        }
        return new ResponseEntity<>(yxInvestOrderService.queryAll(criteria, pageable), HttpStatus.OK);
    }

    @PostMapping
    @Log("新增认购订单")
    @ApiOperation("新增认购订单")
    public ResponseEntity<Object> create(@Validated @RequestBody YxInvestOrder resources) {
        return new ResponseEntity<>(yxInvestOrderService.create(resources), HttpStatus.CREATED);
    }

    @PutMapping
    @Log("修改认购订单")
    @ApiOperation("修改认购订单")
    public ResponseEntity<Object> update(@Validated @RequestBody YxInvestOrder resources) {
        yxInvestOrderService.update(resources);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @Log("删除认购订单")
    @ApiOperation("删除认购订单")
    @DeleteMapping
    public ResponseEntity<Object> deleteAll(@RequestBody Integer[] ids) {
        yxInvestOrderService.deleteAll(ids);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @Log("支付")
    @GetMapping("/pay/{id}")
    public void pay(@PathVariable String id) {
        try {
            //更新说商品投资状态
            List<Integer> listProductId = yxInvestOrderService.findListProductId(Integer.parseInt(id));
            for (Integer ProductId : listProductId) {
                yxInvestOrderService.updateIsInvested(ProductId, 1, "");
            }
            YxInvestOrder resources = new YxInvestOrder();
            resources.setId(Integer.parseInt(id));
            resources.setPaid(1);
            resources.setPayTime(new Date());
            resources.setInvestStatus(2);
            yxInvestOrderService.update(resources);
        } catch (Exception e) {
            log.error(e.toString());
            throw new BadRequestException("支付失败");
        }
    }

    @Log("审核")
    @PostMapping("/audit")
    public void audit(@RequestBody YxInvestOrder resources, HttpServletRequest request, HttpServletResponse response) {
        try {
            String produtName = "";
            //审核通过
            if (resources.getAuditStatus() == 1) {
                resources.setInvestStatus(3);
                //{"type":"investSuccess","msg":"恭喜陈**先生认购成功，金额为18000元" }
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("type", "investSuccess");
                String investName = desensitizedName(resources.getInvestName());//认购人姓名
                String msg = "恭喜" + investName + "先生认购成功,金额为" + resources.getPrice() + "元";
                map.put("msg", msg);
                SocketMsg socketMsg = new SocketMsg(JSONObject.toJSONString(map), MsgType.INFO);
                WebSocketServer.sendInfo(socketMsg, null);

                List<Integer> listProductId = yxInvestOrderService.findListProductId(resources.getId());
                if (listProductId != null && listProductId.size() > 0) {
                    StringBuffer sbf = new StringBuffer();
                    for (Integer ProductId : listProductId) {
                        YxStoreProductDTO productDto = yxStoreProductService.findById(ProductId);
                        if (productDto != null && StringUtils.isNotEmpty(productDto.getStoreName())) {
                            sbf.append(productDto.getStoreName());
                            sbf.append(",");
                        }
                        //更新说商品投资状态
                        yxInvestOrderService.updateIsInvested(ProductId, 1, investName);
                    }
                    if (sbf.length() > 0) {
                        produtName = sbf.substring(0, sbf.toString().length() - 1);
                    }

                }
                YxInvestOrderDto dto = yxInvestOrderService.findById(resources.getId());
                dto.setProdutName(produtName);
                YxSystemConfig config = yxSystemConfigService.findByKey("invest_sale_agreement");
                if (StringUtils.isNotEmpty(config.getValue())) {
                    //销售合同
                    String saleContractUrl = generatePDF(response, request, config.getValue(), dto, dto.getOrderId() + "sales");
                    resources.setSaleContractUrl(saleContractUrl);
                }
                YxSystemConfig config1 = yxSystemConfigService.findByKey("invest_contract");
                if (StringUtils.isNotEmpty(config1.getValue())) {
                    //买卖合同
                    String contractUrl = generatePDF(response, request, config1.getValue(), dto, dto.getOrderId() + "contract");
                    resources.setContractUrl(contractUrl);
                }

            } else {
                //更新说商品投资状态
                List<Integer> listProductId = yxInvestOrderService.findListProductId(resources.getId());
                for (Integer ProductId : listProductId) {
                    yxInvestOrderService.updateIsInvested(ProductId, 0, "");
                }
            }

            resources.setAuditTime(new Date());
            resources.setAuditor(SecurityUtils.getUsername());
            yxInvestOrderService.update(resources);
        } catch (Exception e) {
            log.info(e.getMessage());
            throw new BadRequestException("审核异常");
        }
    }

    /**
     * @param response
     * @param request
     * @param details      合同内容详情
     * @param dto
     * @param contractName 合同名
     * @return
     */
    public String generatePDF(HttpServletResponse response, HttpServletRequest request, String details, YxInvestOrderDto dto, String contractName) {

        Document document = new Document();
        //生成PDF临时文件
        String pdfPath = request.getSession().getServletContext().getRealPath("/") + contractName + ".pdf";
        String pdfUrl = "";
        SimpleDateFormat sdff = new SimpleDateFormat("yyyy年MM月dd日");
        try {
            //下载导出设置
//            response.setContentType("application/pdf");
//            response.addHeader("Content-Disposition", "attachment;filename=" +
//                    new String(("协议合同" + ".pdf").getBytes(), "iso-8859-1"));
//            PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdfPath));
            document.open();
            StringBuffer buf = new StringBuffer(details);
            //替换变量
            details = details.replace("investName", dto.getInvestName()).replace("investPhone", dto.getInvestPhone());
            details = details.replace("price", String.valueOf(dto.getPrice())).replace("produtName", dto.getProdutName());
            details = details.replace("newBeginTime", sdff.format(dto.getBeignDate())).replace("newEndTime", sdff.format(dto.getEndDate()));
            details = details.replace("address", "").replace("investBankCard", dto.getInvestBankCard());
            details = details.replace("investBankName", dto.getInvestBankName()).replace("nowTime", sdff.format(new Date()));
            details = details.replace("signPicUrl", "<img src=\"" + dto.getSignPicUrl() + "\" class=\"head_pic\" mode=\"widthFix\" style=\"width: 200px;height: 50px\"/>");
            //在下面，body中设置了style，设置了默认字体为宋体，这样导出时的html语言就默认带有了字体，汉字才会导出成功
            String content = "<html><body style=\"font-family: 宋体, SimHei;\">" + "<p style=\"text-align: center;\">" +
                    "<span style=\"font-family: 黑体, SimHei; font-size: 24px;\">" + "" + "</span></p>"
                    + details + "</body></html>";
            //这里是必须要设置编码的，不然导出中文就会乱码。
            byte b[] = content.getBytes("utf-8");
            //将字节数组包装到流中
            ByteArrayInputStream bais = new ByteArrayInputStream(b);
            //自定义字体调用方法
//            XMLWorkerHelper.getInstance().parseXHtml(writer, document, bais, Charset.forName("UTF-8"),new MyFontsProvider());
            //生成PDF文件
            XMLWorkerHelper.getInstance().parseXHtml(writer, document, bais, Charset.forName("UTF-8"));
            bais.close();
            document.close();
            //上传到腾讯云
            QiniuConfig qiniuConfig = qiNiuService.find();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
            SimpleDateFormat sdf1 = new SimpleDateFormat("MM");
            //完成目录加文件名
            String fullpath = sdf.format(new Date()) + "/" + sdf1.format(new Date()) + "/" + contractName + ".pdf";
            File file = new File(pdfPath);
            InputStream in = new FileInputStream(file);
            TencentCOSUtils.uploadfile(in, fullpath, qiniuConfig);
            in.close();
            //删除完成删除本地文件
            file.delete();
            pdfUrl = qiniuConfig.getHost() + "/" + fullpath;
            log.info("认购订单审核通过合同上传完成路径：" + qiniuConfig.getHost() + "/" + fullpath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return pdfUrl;
    }


    //名字脱敏
    private static String desensitizedName(String fullName) {
        if (!Strings.isNullOrEmpty(fullName)) {
            String name = StringUtils.left(fullName, 1);
            return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
        }
        return fullName;
    }

    @Log("下载合同")
    @GetMapping("/downLoadPDF/{id}/{template}")
    public void downLoadPDF(@PathVariable String id, HttpServletResponse response, @PathVariable String template) {
        try {
            YxInvestOrderDto yxInvestOrder = yxInvestOrderService.findById(Integer.parseInt(id));
            //买卖合同
            String fileUrl = "";
            if ("contract".equals(template)) {
                fileUrl = yxInvestOrder.getContractUrl();
            } else if ("sales".equals(template)) {
                //销售合同
                fileUrl = yxInvestOrder.getSaleContractUrl();
            }

            response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode("合同" + ".pdf", "UTF-8"));
            OutputStream os = response.getOutputStream();
            byte[] buf = new byte[8192];
            int len;
            URL url = new URL(fileUrl);
            InputStream inputStream = url.openStream();
            BufferedInputStream bis = new BufferedInputStream(inputStream);
            while ((len = bis.read(buf)) > 0) {
                os.write(buf, 0, len);
            }
            if (inputStream != null) {
                inputStream.close();
            }
            os.flush();
            os.close();
        } catch (Exception e) {
            log.error(e.toString());
            throw new BadRequestException("下载失败，请联系管理员！");
        }
    }

    @Log("取消认购订单")
    @ApiOperation("取消认购订单")
    @PostMapping("/cancelSubscrip")
    public ResponseEntity<Object> cancelSubscrip(@Validated @RequestBody YxInvestOrder resources) {
        YxInvestOrderDto dto = yxInvestOrderService.findById(resources.getId());
        resources.setRefunder(SecurityUtils.getUsername());
        resources.setInvestStatus(9);
        //二维码扫码支付的订单退款
        if ("2".equals(dto.getPayType())) {
            RefundApplyCriteia criteia = new RefundApplyCriteia();
            //这里退款的金额单位是分，所以乘以100
            criteia.setRefundFee(dto.getPrice().longValue()*100);
            //测试使用
//            criteia.setRefundFee(1L);
            criteia.setOutRefundNo(dto.getOrderId());
            criteia.setOutTradeNo(dto.getOrderTradeNo());
            Map<String, Object> map=kryConfigService.refundApply(criteia);
            if("0".equals(map.get("status").toString())){
                   JSONObject obj= JSON.parseObject(map.get("resultParams").toString());
                   if(obj.getInteger("code")==0){
                       JSONObject resultObj= JSON.parseObject(obj.get("result").toString());
                       resources.setRefundPrice(BigDecimal.valueOf(dto.getPrice()));
                       if("SUCCESS".equals(resultObj.getString("refundStatus"))){
                           resources.setRefundReasonTime(new Date());
                           resources.setRefundStatus(2);
                       }else{
                           resources.setRefundStatus(1);
                       }
                   }else{
                       throw new BadRequestException(obj.getString("message"));
                   }
            }else{
                throw new BadRequestException(map.get("errorMsg").toString());
            }
        }else{
            //前台支付
            resources.setRefundReasonTime(new Date());
        }
        yxInvestOrderService.update(resources);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

}